'''
Created on 24/10/2012

@author: Chris
'''

from Tkinter import Tk, Toplevel, Label, Entry, Text, Spinbox, Checkbutton, END, IntVar, StringVar, BOTH, W, N, E, S, RAISED, RIGHT,TOP
from tkFileDialog import askdirectory
from ttk import Combobox, Style, Button
from ttk import Frame as TFrame
import tkMessageBox, re
from util import report_exception, is_file_name_existed

#=======================================================================================
class AddRepoDialog(Toplevel):
#=======================================================================================

#=======================================================================================
    def __init__(self, controller, master=None):
#=======================================================================================
        Toplevel.__init__(self, master)
        self.title("Create a repository")
                
        label1 = Label(self, text="Repository Name: ")
        label1.grid(column=0, row=0) 
        
        self.__entry_name = Entry(self)
        self.__entry_name.grid(column=1, row=0, pady=7) 
        
        label2 = Label(self, text="Repository Directory: ")
        label2.grid(column=0, row=1, sticky=W+N)
        self.__entry_dir = Entry(self)
        self.__entry_dir.grid(column=1, row=1, pady=7)    
        
        btn_open_dlg = Button(self, text="Open", command=self.__select_repo_dlg)
        btn_open_dlg.grid(column=0, row=2, padx=5, pady=4)
        
        btn_confirm = Button(self, text='OK', command=self.__confirm)
        btn_confirm.grid(column=1, row=2, padx=5, pady=4 )

        
        self.rowconfigure(0, pad=7)
        self.rowconfigure(1, pad=7)
        self.columnconfigure(0, pad=7)
        self.columnconfigure(1, pad=7)
        self.resizable(width=False, height=False)
        
        self.selected_repo_dir = ''
        self.selected_repo_name = ''
        self.controller = controller
        
#=======================================================================================
    def __select_repo_dlg(self):
#=======================================================================================
        self.__entry_dir.delete(0, END)
        
        options = {}
        options['title']      = 'Select Repository Directory'
        options['parent']     = self.controller.root
        options['mustexist']  = False
        options['initialdir'] = self.controller.get_work_dir()

        self.selected_repo_dir = askdirectory(**options)
        self.__entry_dir.insert(0, self.selected_repo_dir)
        
#=======================================================================================
    def __confirm(self):
#=======================================================================================
        self.selected_repo_name = self.__entry_name.get()
        self.selected_repo_dir = self.__entry_dir.get()
        
        if (self.selected_repo_name is None) or (self.selected_repo_name == '') \
            or (self.selected_repo_dir is None) or (self.selected_repo_dir == ''):
            err_msg = "Repository name and directory are required!"
            tkMessageBox.showerror("Error", err_msg)
            
        else:
            config = self.controller.get_config()
            if not config.is_repo_name_valid(self.selected_repo_name):
                err_msg = "Repository name: \"%s\" is already exist, please input a unique name!"%self.selected_repo_name
                tkMessageBox.showerror("Repository Name Error", err_msg)
        
        self.destroy()    
#        return (self.selected_repo_name, self.selected_repo_dir)
#=======================================================================================
    def get_repo_info(self):
#=======================================================================================            
        return (self.selected_repo_name, self.selected_repo_dir)


#=======================================================================================
class AddCommentDialog(Toplevel):
#=======================================================================================

#=======================================================================================
    def __init__(self, master=None):
#=======================================================================================
        Toplevel.__init__(self, master)
        self.title("Add comment")
        label1 = Label(self, text="Plase input comments")
        label1.grid(column=0, row=0, sticky=W, pady=4, padx=5) 
        
        self.comment_text = Text(self,height=10,width=50,background='white')
        self.comment_text.grid(row=1, column=0, columnspan=2, rowspan=4, 
                               padx=5, pady=7, sticky=E+W+S+N) 
         
        btn_confirm = Button(self, text='Confirm', command=self.__confirm)
        btn_confirm.grid(row=1, column=3)
        btn_cancel = Button(self, text='Clear', command=self.__clear)
        btn_cancel.grid(row=2, column=3, pady=4)    
        

        self.columnconfigure(3, pad=7)
        self.rowconfigure(5, pad=7)
        self.resizable(width=False, height=False)
        # save comment
        self.__comment = ""
        
#=======================================================================================
    def __validate_comment(self):
#=======================================================================================
        '''
        description: validate the inputed comment, the comment is required
        return     : return true if text area (comment) is filled otherwise false
        '''        
        contents = self.comment_text.get(1.0, END)

        if contents == "" or contents is None or len(contents) == 1:
            report_exception("Comment is required!")
            return False
                        
        return True
            
#=======================================================================================
    def __confirm(self):
#=======================================================================================
        '''
        description: validate the comment textarea and save the comment
        '''  
        if not self.__validate_comment():
            self.comment_text.focus_set()
        else:
            self.__comment = self.comment_text.get(1.0, END)
            self.destroy()    

#=======================================================================================
    def __clear(self):
#=======================================================================================
        '''
        description: clear the contents(the comment) of text widget
        '''  
        self.comment_text.delete(1.0, END)  

#=======================================================================================
    def get_comment(self):
#======================================================================================= 
        '''
        description: get the comment
        '''           
        return self.__comment      
    
    
#=======================================================================================
class RenameDialog(Toplevel):
#=======================================================================================
    '''
    Dialog for rename file in git
    '''
#=======================================================================================
    def __init__(self, file_path, master=None):
#=======================================================================================
        Toplevel.__init__(self, master)
        self.title("Rename file")
        
        label1 = Label(self, text="Please input new file name:")
        label1.grid(column=0, row=0, sticky=W, pady=4, padx=5) 
        
        self.new_name_entry = Entry(self, width=30)
        self.new_name_entry.grid(column=0, row=1, columnspan=3, sticky=W, pady=4, padx=5) 
         
        btn_confirm = Button(self, text='Confirm', command=self.__confirm)
        btn_confirm.grid(column=0, row=2, padx=4, pady=4, sticky=W)
        btn_cancel = Button(self, text='Clear', command=self.__clear)
        btn_cancel.grid(column=2, row=2, padx=4, pady=4)    
        
        self.columnconfigure(0, pad=7)
        self.columnconfigure(2, pad=7)
        self.resizable(width=False, height=False)
        # save new file name
        self.__new_file_name = ""
        self.__file_path = file_path
#=======================================================================================
    def __validate_name(self):
#=======================================================================================
        '''
        description: validate the inputed file name, the comment is required
        return     : return (true, null-msg) if file name is valid, otherwise (false, msg)
        '''        
        new_file_name = self.new_name_entry.get()
        
        if new_file_name is None or len(new_file_name) <= 0:
            msg = "plase input file name!"
            return False, msg
        
        regex = r"\W+"
        patrn = re.compile(regex)
        if patrn.findall(new_file_name) is None:
            msg = "file name can't contain special characters!"
            return False, msg
        elif is_file_name_existed(new_file_name, self.__file_path):
            msg = "file name is already exist!"
            return False, msg
        return True, ""
            
#=======================================================================================
    def __confirm(self):
#=======================================================================================
        '''
        description: validate the file name and save it
        '''  
        result, msg = self.__validate_name()
        if not result:
            report_exception(msg)
            self.__clear()
            self.new_name_entry.focus_set()
        else:
            self.__new_file_name = self.new_name_entry.get()
            self.destroy()    

#=======================================================================================
    def __clear(self):
#=======================================================================================
        '''
        description: clear the contents of file name entry
        '''  
        self.new_name_entry.delete(0, END)  

#=======================================================================================
    def get_new_file_name(self):
#======================================================================================= 
        '''
        description: get the new file name
        '''           
        return self.__new_file_name   


#=======================================================================================
class SearchDialog(Toplevel):
#=======================================================================================
    '''
    Dialog for searching keywords in git comment
    '''
#=======================================================================================
    def __init__(self, master=None):
#=======================================================================================
        Toplevel.__init__(self, master)
        
        self.title("Search in comment")
        label1 = Label(self, text="Please input keywords for searching:")
        label1.grid(column=0, row=0, sticky=W, pady=4, padx=5) 
        
        self.keywords_entry = Entry(self, width=50)
        self.keywords_entry.grid(column=0, row=1, columnspan=2, sticky=W, pady=4, padx=5) 
         
        btn_confirm = Button(self, text='OK', command=self.__confirm)
        btn_confirm.grid(column=0, row=2, sticky=W, padx=7, pady=4)
        btn_cancel = Button(self, text='Clear', command=self.__clear)
        btn_cancel.grid(column=1, row=2, sticky=E, padx=7, pady=4)    
        
        self.resizable(width=False, height=False)
        # save keywords
        self.__keywords = ""
#=======================================================================================
    def __validate_keywords(self):
#=======================================================================================
        '''
        description: validate keywords, it is non-empty
        return     : return true if keyword is given
        '''        
        keywords = self.keywords_entry.get()
        
        if keywords is None or len(keywords) <= 0:
            msg = "plase input keywords!"
            return False, msg
        
        return True, ""
            
#=======================================================================================
    def __confirm(self):
#=======================================================================================
        '''
        description: validate the keywords and save it
        '''  
        result, msg = self.__validate_keywords()
        if not result:
            report_exception(msg)
            self.__clear()
            self.keywords_entry.focus_set()
        else:
            self.__keywords = self.keywords_entry.get()
            self.destroy()    

#=======================================================================================
    def __clear(self):
#=======================================================================================
        '''
        description: clear the contents of keyword entry
        '''  
        self.keywords_entry.delete(0, END)  

#=======================================================================================
    def get_keywords(self):
#======================================================================================= 
        '''
        description: get keyword
        '''           
        return self.__keywords    
    

#=======================================================================================
class AutoSaveDialog(Toplevel):
#=======================================================================================
    '''
    Dialog for setting auto save function
    '''
    # default timer for saving function is from 1 to 30 minute
    min_default_interval = 1
    max_default_interval = 30
#=======================================================================================
    def __init__(self, repo_config, timer, master=None):
#=======================================================================================
        '''
        parameter: repo_config, repository config, its dictionary, key: repo_name value: repo_attribute
        '''
        
        Toplevel.__init__(self, master)
        self.title("Auto save config")
        
        
        label1 = Label(self, text="Timer (minute):")
        label1.grid(column=0, row=0, sticky=N+W, pady=4, padx=5) 
        
        self.timer_box = Spinbox(self, from_= AutoSaveDialog.min_default_interval, 
                                       to=AutoSaveDialog.max_default_interval)
        
        # set timer from config file
        if timer != -1:
            self.timer_box.delete(0,END)
            self.timer_box.insert(0, timer)
        else:
            self.timer_box.delete(0,END)
            self.timer_box.insert(0, AutoSaveDialog.min_default_interval)
            
        self.timer_box.grid(column=1, row=0, sticky=N+W, pady=4, padx=5 ) 
        
        label2 = Label(self, text="Please ticket the repository name for auto save:")
        label2.grid(column=0, columnspan=2, row=1, sticky=N+W, pady=4, padx=5) 
        
        # Checkbuttons for repository, 
        # key: repo_name value: checkbutton instance, intvar associated with checkbutton
        self.repo_chkbtns = {}
        row_index = 2
        for repo_name in repo_config.iterkeys():
            value = repo_config[repo_name]
            var = IntVar()
            check_btn = Checkbutton(self, text = repo_name, onvalue=1, offvalue=0, variable=var)
            check_btn.grid(column=0, columnspan=2, row=row_index, sticky=W, padx=30, pady=2) 
            
            # init check button state
            if value == "yes":
                check_btn.select()
            elif value == "no":
                check_btn.deselect()
                
            self.repo_chkbtns[repo_name] = (check_btn, var)     
            row_index += 1
            
        btn_confirm = Button(self, text='Confirm', command=self.__confirm)
        btn_confirm.grid(column=0, row=row_index, sticky=N+W, pady=4, padx=7)
        btn_cancel = Button(self, text='Cancel', command=self.__cancel)
        btn_cancel.grid(column=1, row=row_index, sticky=N+E, pady=4, padx=7)    
        
        
        self.resizable(width=False, height=False)
        
        
        self.__repo_config = repo_config
        self.__timer = timer
        
        # save auto save value for repository
        # key: repo_name value: yes for enable auto saving and no for disable
        self.__repo_selection = {}
        # save keywords
        self.__interval = 0
        
       

        
#=======================================================================================
    def __validate_time_interval(self):
#=======================================================================================
        '''
        description: validate keywords, it is non-empty
        return     : return true if keyword is given
        '''       
        try:
            interval_time = int(self.timer_box.get())
        except ValueError:
            report_exception("Please input integer for timer!")
            return False
        
        return True
            
#=======================================================================================
    def __confirm(self):
#=======================================================================================
        '''
        description: validate the keywords and save it
        '''  
        result = self.__validate_time_interval()
        if not result:
            self.timer_box.delete(0, END)
            if self.__timer == -1:
                self.timer_box.insert(0, AutoSaveDialog.min_default_interval)
            else:
                self.timer_box.insert(0, self.__timer)
                
            self.__clear()
            self.timer_box.focus_set()
        else:
            self.__interval = int(self.timer_box.get())
            
            # get the selections from check button
            for repo_name, (check_btn,var) in self.repo_chkbtns.iteritems():
                if var.get() == 1:
                    self.__repo_selection[repo_name] = "yes"
                elif var.get() == 0:
                    self.__repo_selection[repo_name] = "no"
                    
            self.destroy()    

#=======================================================================================
    def __cancel(self):
#=======================================================================================
        '''
        description: reset the original selection of repository auto-save config
        '''  
        # reset timer
        self.timer_box.delete(0, END)
        if self.__timer == -1:
            self.timer_box.insert(0, AutoSaveDialog.min_default_interval)
        else:
            self.timer_box.insert(0, self.__timer)
        
        # reset check button
        for repo_name, (check_btn,var) in self.repo_chkbtns.iteritems():
            if self.__repo_config[repo_name] == "yes":
                check_btn.select()
            elif self.__repo_config[repo_name] == "no":
                check_btn.deselect()
        self.destroy()
#=======================================================================================
    def get_auto_config(self):
#======================================================================================= 
        '''
        description: get keyword
        '''           
        return self.__interval, self.__repo_selection        


#=======================================================================================
    def is_config_changed(self):
#======================================================================================= 
        
        for repo_name in self.__repo_selection:
            if self.__repo_selection[repo_name] != self.__repo_config[repo_name]:
                return True
        
        if self.__interval != self.__timer:
            return True
        
        return False

#=======================================================================================
class CompareDialog(Toplevel):
#=======================================================================================
    '''
    Dialog for comparing two versions in file history
    '''
#=======================================================================================
    def __init__(self, file_name, blob_list, master=None):
#=======================================================================================
        '''
        parameter: repo_config, repository config, its dictionary, key: repo_name value: repo_attribute
        '''
        
        Toplevel.__init__(self, master)
        title_text = "Compare history versions"
        self.title(title_text)
        
        label_text = "Select two history versions of "+ file_name
        label1 = Label(self, text=label_text)
        label1.grid(column=0, row=0, sticky=W, pady=4, padx=5) 
        
        
        label2 = Label(self, text="left side file")
        label2.grid(column=0, row=1, sticky=W, pady=4, padx=5) 
        
        file_box_value = self.__convert_blob_index_to_values(blob_list)
        
        self.left_file_value = StringVar()
        self.left_file_box = Combobox(self, textvariable=self.left_file_value, state='readonly')
        self.left_file_box.grid(column=0, row=2, sticky=W, pady=4, padx=5)
        self.left_file_box['values'] = file_box_value
        self.left_file_box.current(0)
        
        
        label3 = Label(self, text="right side file")
        label3.grid(column=1, row=1, sticky=W, pady=4, padx=5) 
        
        self.right_file_value = StringVar()
        self.right_file_box = Combobox(self, textvariable=self.right_file_value, state='readonly')
        self.right_file_box.grid(column=1, row=2, sticky=W, pady=4, padx=5)
        self.right_file_box['values'] = file_box_value
        self.right_file_box.current(0)
        
        btn_confirm = Button(self, text='OK', command=self.__confirm)
        btn_confirm.grid(column=1, row=3, sticky=E, pady=4, padx=7)
        
        self.resizable(width=False, height=False)
        
        self.file_name = file_name
        self.blob_list = blob_list
        self.__left_blob = None
        self.__right_blob = None


#=======================================================================================
    def __convert_blob_index_to_values(self, blob_list):
#=======================================================================================
        '''
        description: convert blob index to combox values
        parameter  : blob_list, a list of git blobs
        '''  
        max_index = len(blob_list)+1
        combox_values = tuple(["version-"+str(i) for i in range(1, max_index)])
        return combox_values

#=======================================================================================
    def __find_blob_by_selection(self, is_left_side=True):
#=======================================================================================
        '''
        description: convert blob index to combox values
        parameter  : blob_list, a list of git blobs
        '''  
        selection = ''
        if is_left_side:
            selection = self.left_file_value.get()
        else:
            selection = self.right_file_value.get()
            
        index = int(selection.split('-')[1])-1
        
        if index >= 0 and index < len(self.blob_list):
            blob, commit = self.blob_list[index]
            return blob
        
        return None
            
#=======================================================================================
    def __confirm(self):
#=======================================================================================
        '''
        description: validate the keywords and save it
        ''' 
        
        self.__left_blob = self.__find_blob_by_selection()
        self.__right_blob = self.__find_blob_by_selection(False)
         
        self.destroy()    

#=======================================================================================
    def get_blobs_for_comparison(self):
#======================================================================================= 
        '''
        description: get selected two file versions, left-side and right-side
        '''           
        left_version = self.left_file_value.get()
        right_version = self.right_file_value.get()
        return self.__left_blob,left_version, self.__right_blob,right_version      


#=======================================================================================
class AboutDialog(Toplevel):
#=======================================================================================
    '''
    About dialog
    '''
#=======================================================================================
    def __init__(self, master=None):
#=======================================================================================
         
        Toplevel.__init__(self, master, width=800, height=600)
        self.title("About Draft Manager")

        frame = TFrame(self)
        frame.grid(padx=5,pady=5, sticky=W)
        
        version_info = "Draft Manger version 1.0 \n\n"
        version_info += "\tAuthors : Giovanni Moretti and Chris Tylor"
        info = Label(frame, text=version_info)
        info.grid(column=0, columnspan=5, row=0, rowspan=5, padx=5,pady=10, sticky=W)

        ok_btn = Button(frame, text="OK", command=self.destroy)
        ok_btn.grid(column=4, row=5, padx=5, pady=5, sticky=E+S)
        self.resizable(width=False, height=False)

  
#
#root = Tk()
#a = AboutDialog(root)
#root.mainloop()         